package cn.iocoder.yudao.module.design.controller.admin.house;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.design.controller.admin.flow.vo.FlowCreateReqVO;
import cn.iocoder.yudao.module.design.controller.admin.house.vo.*;
import cn.iocoder.yudao.module.design.controller.admin.houseUserRel.vo.UserRelListVO;
import cn.iocoder.yudao.module.design.dal.dataobject.flow.FlowDO;
import cn.iocoder.yudao.module.design.dal.dataobject.flowmd.FlowMdDO;
import cn.iocoder.yudao.module.design.dal.dataobject.house.HouseDO;
import cn.iocoder.yudao.module.design.dal.dataobject.houseUserRel.HouseUserRelDO;
import cn.iocoder.yudao.module.design.dal.dataobject.pic.PicDO;
import cn.iocoder.yudao.module.design.dal.dataobject.relatived.RelativedDO;
import cn.iocoder.yudao.module.design.enums.common.CommStatusEnum;
import cn.iocoder.yudao.module.design.enums.design.*;
import cn.iocoder.yudao.module.design.enums.user.DesignUserRoleEnum;
import cn.iocoder.yudao.module.design.service.flow.FlowService;
import cn.iocoder.yudao.module.design.service.flowmd.FlowMdService;
import cn.iocoder.yudao.module.design.service.flowtask.FlowTaskService;
import cn.iocoder.yudao.module.design.service.house.HouseService;
import cn.iocoder.yudao.module.design.service.house.bo.NodeItemDataBO;
import cn.iocoder.yudao.module.design.service.houseUserRel.HouseUserRelService;
import cn.iocoder.yudao.module.design.service.node.NodeService;
import cn.iocoder.yudao.module.design.service.pic.PicService;
import cn.iocoder.yudao.module.design.service.relatived.RelativedService;
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
import cn.iocoder.yudao.module.infra.service.config.ConfigService;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.order.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
import cn.iocoder.yudao.module.pay.service.demo.PayDemoOrderService;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.design.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.WALLET_BALANCE_NOT_ENOUGH;

@Tag(name = "管理后台 - 项目业务")
@RestController
@RequestMapping("/design/house")
@Validated
@Slf4j
public class HouseBusinessController {

    @Resource
    private HouseService houseService;

    @Resource
    private HouseUserRelService houseUserRelService;

    @Resource
    private FlowService flowService;

    @Resource
    private NodeService nodeService;

    @Resource
    private PicService picService;

    @Resource
    private FlowMdService flowMdService;
//    @Resource
//    private PayWalletService payWalletService;
//
//    @Resource
//    private PayDemoOrderService payDemoOrderService;

//    @Resource
//    private PayOrderService orderService;
//    @Resource
//    private PayAppService appService;

    @Resource
    private FlowTaskService flowTaskService;

    @Resource
    private AdminUserService userService;

    @Resource
    private RelativedService relativedService;
    // 参数配置
    @Resource
    private ConfigService configService;


    /**
     * infa config 配置key
     */
    public static final String POINS_CONFIG_KEY = "expend_points";


    public static final List<Long> FILTER_ROLE_IDS = CollUtil.toList(DesignUserRoleEnum.BUSINESS_MANAGER.getRoleId(),
            DesignUserRoleEnum.PROJECT_MANAGER.getRoleId(),
            DesignUserRoleEnum.STOREKEEPER.getRoleId(),
            DesignUserRoleEnum.CUST_SERVICE.getRoleId()
    );


    @PostMapping("/createHouseOne")
    @Operation(summary = "创建项目-步骤1")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> createHouseOne(@Valid @RequestBody HouseOneReqVO createReqVO) {
        if (ObjectUtil.isEmpty(createReqVO.getDesignerId())) {
            createReqVO.setDesignerId(SecurityFrameworkUtils.getLoginUserId());
        }
        //查询业主是否新建  没有新建则新建 新建则返回
        Long ownerId = createReqVO.getOwnerId();
        if (ObjectUtil.isEmpty(ownerId)) {
            ownerId = houseService.createUserRel(createReqVO.getOwnerName(), createReqVO.getOwnerTel()
                    , DesignUserRoleEnum.OWNER.getRoleId().toString());
            createReqVO.setOwnerId(ownerId);
        } else {
            AdminUserDO ownerInfo = userService.getUser(ownerId);
            if (!ownerInfo.getMobile().equals(createReqVO.getOwnerTel())) {
                ownerId = houseService.createUserRel(createReqVO.getOwnerName(), createReqVO.getOwnerTel()
                        , DesignUserRoleEnum.OWNER.getRoleId().toString());
                createReqVO.setOwnerId(ownerId);
            }
        }
        // 创建项目  保存基本信息
        Long houseId = houseService.createBusinessHouse(createReqVO);

        // 保存 业主
        houseUserRelService.saveHouseUserRel(houseId, createReqVO.getOwnerId(), DesignUserRoleEnum.OWNER.getRoleId());
        // 保存 设计师
        houseUserRelService.saveHouseUserRel(houseId, createReqVO.getDesignerId(), DesignUserRoleEnum.DESIGN.getRoleId());

        return success(houseId);
    }

    @PostMapping("/updateHouseOne")
    @Operation(summary = "修改项目步骤1")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> updateHouseOne(@Valid @RequestBody HouseOneReqVO createReqVO) {
        if (ObjectUtil.isEmpty(createReqVO.getDesignerId())) {
            createReqVO.setDesignerId(SecurityFrameworkUtils.getLoginUserId());
        }
        //查询业主是否新建  没有新建则新建 新建则返回
        Long ownerId = createReqVO.getOwnerId();
        if (ObjectUtil.isEmpty(ownerId)) {
            ownerId = houseService.createUserRel(createReqVO.getOwnerName(), createReqVO.getOwnerTel()
                    , DesignUserRoleEnum.OWNER.getRoleId().toString());
            createReqVO.setOwnerId(ownerId);
        } else {
            // 判断和源数据手机号是否一致
            AdminUserDO ownerInfo = userService.getUser(ownerId);
            if (!ownerInfo.getMobile().equals(createReqVO.getOwnerTel())) {
                ownerId = houseService.createUserRel(createReqVO.getOwnerName(), createReqVO.getOwnerTel()
                        , DesignUserRoleEnum.OWNER.getRoleId().toString());
                createReqVO.setOwnerId(ownerId);
            }
        }
        // 创建项目  保存基本信息
        houseService.updateBusinessHouse(createReqVO);
//        houseUserRelService.deleteHouseUseRel(createReqVO.getId(),  DesignUserRoleEnum.OWNER.getRoleId());
        // 保存 业主
        houseUserRelService.saveHouseUserRel(createReqVO.getId(), createReqVO.getOwnerId(), DesignUserRoleEnum.OWNER.getRoleId());
//        // 保存 设计师
        houseUserRelService.saveHouseUserRel(createReqVO.getId(), createReqVO.getDesignerId(), DesignUserRoleEnum.DESIGN.getRoleId());

        return success(createReqVO.getId());
    }

    @GetMapping("/getCreateHouseOne/{id}")
    @Operation(summary = "根据Id获取步骤1数据")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('design:house:query')")
    public CommonResult<HouseOneResVO> getCreateHouseOne(@PathVariable Long id) {
        // 查询项目基本信息
        HouseOneResVO houseRespVO = houseService.getHouseOneById(id);
        // 查询 业主信息
        AdminUserDO ownerInfo = userService.getUser(houseRespVO.getOwnerId());
        houseRespVO.setOwnerName(ownerInfo.getNickname());
        houseRespVO.setOwnerTel(ownerInfo.getMobile());
        return success(houseRespVO);
    }

    @PostMapping("/createHouseTwo")
    @Operation(summary = "创建项目步骤2-补充相关人员")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> createHouseTwo(@Valid @RequestBody HouseTwoReqVO createReqVO) {
        log.debug("========  补充相关人员  同步任务 start ==============");
        createHouseTwoAsync(createReqVO);
        log.debug("========  补充相关人员  同步任务 end ==============");
        return success(1L);
    }

    @Async
    public void createHouseTwoAsync(HouseTwoReqVO createReqVO) {
        log.debug("========  补充相关人员  Async start ==============");
        houseService.validateHouseExists(createReqVO.getId());
        List<HouseTwoUserReqVO> userList = createReqVO.getUserList();
        // 过滤 mobile 和 nickName 都为空的数据
        List<HouseTwoUserReqVO> filteredList = userList.stream()
                .filter(user -> StrUtil.isNotEmpty(user.getMobile()) && StrUtil.isNotEmpty(user.getNickName()))
                .collect(Collectors.toList());
        for (HouseTwoUserReqVO userReq : filteredList) {
            //查询用户是否新建  没有新建则新建 新建则返回
            Long userId = null;
            //查询用户是否新建  没有新建则新建 新建则返回
            userId = houseService.createUserRel(userReq.getNickName(), userReq.getMobile()
                    , userReq.getRoleId().toString());
//            补充userId
//            userReq.setId(ownerInfo.getId());
//            houseUserRelService.deleteHouseUseRel(createReqVO.getId(), userReq.getRoleId());
            // 如果上面 是存量好友 状态应该为通过 这里项目关联人员状态为0  等待项目启动统一发布任务项目关联任务 同意后改为1
            houseUserRelService.saveHouseUserRel(createReqVO.getId(), userId, userReq.getRoleId());
        }
        log.debug("========  补充相关人员  Async end ==============");
    }

    @GetMapping("/getCreateHouseTwo/{id}")
    @Operation(summary = "获取步骤2-项目相关人员数据")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('design:house:query')")
    public CommonResult<List<HouseTwoUserReqVO>> getCreateHouseTwo(@PathVariable Long id) {
        // 查询项目基本信息
        houseService.validateHouseExists(id);
        // 查询 houseRel ;
        List<HouseTwoUserReqVO> houseTwoUserList = houseUserRelService.getHouseTwoUserList(id, FILTER_ROLE_IDS);

        return success(houseTwoUserList);
    }

    @PostMapping("/createHouseThree")
    @Operation(summary = "创建项目步骤3-保存项目相关附件")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> createHouseThree(@Valid @RequestBody HouseThreeReqVO createReqVO) {

        // 查询项目基本信息
        houseService.validateHouseExists(createReqVO.getId());
        PicDO picDo = new PicDO();
        picDo.setHouseId(createReqVO.getId());
        for (HouseThreeFileReqVO fileReqVO : createReqVO.getFileList()) {

            picDo.setUploadType(fileReqVO.getUploadType());
            picDo.setSourceType(fileReqVO.getSourceType());
            picService.savePicData(picDo, fileReqVO.getFileList());
        }
        return success(createReqVO.getId());
    }

    @GetMapping("/getCreateHouseThree/{id}")
    @Operation(summary = "获取步骤3-项目相关附件数据")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('design:house:query')")
    public CommonResult<HouseThreeResVO> getCreateHouseThree(@PathVariable Long id) {
        // 查询项目基本信息
        houseService.validateHouseExists(id);
        // 查询 houseRel ;
        List<HouseThreeFileResVO> fileList = new ArrayList<>();

        /**=========== 查询图片 ===========*/
        PicDO picDO = new PicDO();
        picDO.setHouseId(id);
        picDO.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_0.getCode());
        List<PicDO> picData = picService.getPicData(picDO);
        // 根据sourceType分组
        Map<String, List<PicDO>> sourceTypeGroups = picData.stream()
                .collect(Collectors.groupingBy(PicDO::getSourceType));
        sourceTypeGroups.forEach((sourceType, itemList) -> {
            HouseThreeFileResVO threeFileResVO = new HouseThreeFileResVO();
            threeFileResVO.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_0.getCode());
            threeFileResVO.setSourceType(sourceType);
            threeFileResVO.setFileName(PicSourceTypeEnum.getNameByCode(sourceType));
            threeFileResVO.setFileList(itemList);
            fileList.add(threeFileResVO);
        });

        /**=========== 查询文件 ===========*/
        picDO.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_1.getCode());
        List<PicDO> picFileData = picService.getPicData(picDO);
        // 根据sourceType分组
        Map<String, List<PicDO>> sourceTypeFileGroups = picFileData.stream()
                .collect(Collectors.groupingBy(PicDO::getSourceType));
        sourceTypeFileGroups.forEach((sourceType, itemList) -> {
            HouseThreeFileResVO threeFileResVO = new HouseThreeFileResVO();
            threeFileResVO.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_1.getCode());
            threeFileResVO.setSourceType(sourceType);
            threeFileResVO.setFileName(PicSourceTypeEnum.getNameByCode(sourceType));
            threeFileResVO.setFileList(itemList);
            fileList.add(threeFileResVO);
        });
        // 返回结果
        HouseThreeResVO houseThreeResVO = new HouseThreeResVO();
        houseThreeResVO.setId(id);
        houseThreeResVO.setFileList(fileList);
        return success(houseThreeResVO);
    }


    @PostMapping("/createHouseThreeTmp")
    @Operation(summary = "保存相关附件 暂未使用")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> createHouseThreeTmp() {
        /**==  图片  ==*/
//        HouseThreeReqVO createReqVO = new HouseThreeReqVO();
//        PicDO picDo = new PicDO();
//        picDo.setHouseId(createReqVO.getHouseId());
//        picDo.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_0.getCode());
//        // 平面
//        picDo.setSourceType(PicSourceTypeEnum.PIC_SOURCE_TYPE_ENUM_007.getCode());
//        picService.savePicData(picDo,createReqVO.getPlaneList());
//        // 效果
//        picDo.setSourceType(PicSourceTypeEnum.PIC_SOURCE_TYPE_ENUM_008.getCode());
//        picService.savePicData(picDo,createReqVO.getEffectList());
//
//        // 全景
//        picDo.setSourceType(PicSourceTypeEnum.PIC_SOURCE_TYPE_ENUM_009.getCode());
//        picService.savePicData(picDo,createReqVO.getFullViewList());
//
//        /**==  文件   ==*/
//        picDo.setUploadType(PicUploadTypeEnum.PIC_UPLOAD_TYPE_ENUM_1.getCode());
//        // 合同
//        picDo.setSourceType(PicSourceTypeEnum.PIC_SOURCE_TYPE_ENUM_011.getCode());
//        picService.savePicData(picDo,createReqVO.getContractList());
//
//        // 附件
//        picDo.setSourceType(PicSourceTypeEnum.PIC_SOURCE_TYPE_ENUM_010.getCode());
//        picService.savePicData(picDo,createReqVO.getFileList());

//        return success(createReqVO.getHouseId());
        return success(1L);
    }


    @PostMapping("/createHouseFour")
    @Operation(summary = "创建项目步骤4-确认创建设计流程")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> createHouseFour(@Valid @RequestBody HouseFourReqVO createReqVO) {
        // 校验项目数据是否存在 不存在报错
        HouseDO houseDO = houseService.validateHouseExists(createReqVO.getId());

        // 判断 当前人员是否是项目关联人员（设计师）
        houseUserRelService.validateUserIsRole(createReqVO.getId(),
                SecurityFrameworkUtils.getLoginUserId(), DesignUserRoleEnum.DESIGN.getRoleId());

        // 查询 该项目是否已经创建过对应流程
        List<FlowDO> designFlowList = flowService.getFlowByHouseIdAndFlowCd(createReqVO.getId(), FlowCdEnum.FLOW_CD_0.getCode());
        // 获取处理人
        HouseUserRelDO designUser =
                houseUserRelService.getHouseUserRelByHouseIdAndRoleId(createReqVO.getId(), DesignUserRoleEnum.DESIGN.getRoleId());
        FlowDO designFlow = new FlowDO();
        // 传入的流程id 查不到就新建流程
        if (designFlowList.size() <= 0) {
            // 新建设计流程
            FlowCreateReqVO designFlowCreate = new FlowCreateReqVO();
            designFlowCreate.setFlowName("设计流程");
            designFlowCreate.setHouseId(createReqVO.getId());
            designFlowCreate.setIsMainCd(CommStatusEnum.NORMAL.getCode().toString());
            designFlowCreate.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_0.getCode());
            designFlowCreate.setFlowCd(FlowCdEnum.FLOW_CD_0.getCode());
            designFlowCreate.setDesignerId(designUser.getUserId());
            designFlowCreate.setDeleted(false);
//            designFlow.setStartTime(new Date());
            designFlowCreate.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
            designFlowCreate.setRemark("系统生成设计流程");
            Long flowId = flowService.createFlow(designFlowCreate);
            // 保存流程id
            designFlow.setId(flowId);
            designFlow.setHouseId(createReqVO.getId());
            designFlow.setIsMainCd(CommStatusEnum.NORMAL.getCode().toString());
            designFlow.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_0.getCode());
            designFlow.setFlowCd(FlowCdEnum.FLOW_CD_0.getCode());
            designFlow.setDesignerId(designUser.getUserId());
            designFlow.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
        } else {
            designFlow = designFlowList.get(0);
            // 删除已存在的节点  仅支持流程是待开始状态的
            if (FlowStatusEnum.FLOW_STATUS_ENUM_0.getCode().equals(designFlow.getStatusCd())) {
                nodeService.deleteNodeByFlowId(designFlow.getId());
            } else {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.FLOW_START_NO_DELETE);
            }

        }
        // 判断是模板新建 还是自定义选择 模板查询对应模板 获取Ids
        //  自定义选择  获取传入的Ids
        // 查询设计流程模板数据对象
        List<FlowMdDO> flowMdList = new ArrayList<>();
        if (FlowMdOptionTypeEnum.FLOW_STATUS_ENUM_0.equals(createReqVO.getFlowMdOptionType())) {
            flowMdList = flowMdService.getFlowMdList(FlowCdEnum.FLOW_CD_0.getCode());
            List<Long> idList = flowMdList.stream()
                    .map(FlowMdDO::getId)
                    .collect(Collectors.toList());

            createReqVO.setIds(idList);
        } else {
            flowMdList = flowMdService.getFlowMdList(createReqVO.getIds());
        }

        NodeItemDataBO context = new NodeItemDataBO();
        context.setHouseId(designFlow.getHouseId());
        context.setFlowId(designFlow.getId());
        context.setDesignerId(designFlow.getDesignerId());
        context.setFlowCd(designFlow.getFlowCd());
        context.setFlowMdIds(createReqVO.getIds());
        context.setOptionData(createReqVO.getOptionData());
        context.setList(flowMdList);
        context.setDealerId(designUser.getUserId());
        houseService.saveNodeItemData(context);

        // 查询 该项目是否已经创建过对应流程
        List<FlowDO> sgFlow = flowService.getFlowByHouseIdAndFlowCd(createReqVO.getId(), FlowCdEnum.FLOW_CD_2.getCode());
        if (sgFlow.size() <= 0) {

            // 新建施工流程
            FlowCreateReqVO constructionFlow = new FlowCreateReqVO();
            constructionFlow.setFlowName("施工流程");
            constructionFlow.setHouseId(designFlow.getHouseId());
            constructionFlow.setIsMainCd("0");
            constructionFlow.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_0.getCode());
            constructionFlow.setFlowCd(FlowCdEnum.FLOW_CD_2.getCode());
            constructionFlow.setDesignerId(designFlow.getDesignerId());
            constructionFlow.setDeleted(false);
            constructionFlow.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
            constructionFlow.setRemark("系统生成施工流程");
            Long sgflowId = flowService.createFlow(constructionFlow);

            // 设计师默认关联 施工流程
            // 当设计师是项目经理时，不会有项目关联任务 所以这里直接 添加userFlowRel
            HouseUserRelDO projectManager =
                    houseUserRelService.getHouseUserRelByHouseIdAndRoleId(createReqVO.getId(), DesignUserRoleEnum.PROJECT_MANAGER.getRoleId());
            if (projectManager != null && projectManager.getUserId().toString().equals(designFlow.getDesignerId().toString())) {
                houseService.saveHouseUserFlowRel(designFlow.getHouseId(), sgflowId, designFlow.getDesignerId(), DesignUserRoleEnum.PROJECT_MANAGER.getRoleId());
            }
            houseService.saveHouseUserFlowRel(designFlow.getHouseId(), sgflowId, designFlow.getDesignerId(), DesignUserRoleEnum.DESIGN.getRoleId());


        }


        return success(1L);
    }

    @GetMapping("/getCreateHouseFour/{id}")
    @Operation(summary = "获取步骤4-确认设计流程数据")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('design:house:query')")
    public CommonResult<HouseThreeResVO> getCreateHouseFour(@PathVariable Long id) {
        // 查询项目基本信息
        houseService.validateHouseExists(id);
        // 判断 当前人员是否是项目关联人员（设计师）
        houseUserRelService.validateUserIsRole(id,
                SecurityFrameworkUtils.getLoginUserId(), DesignUserRoleEnum.DESIGN.getRoleId());

        // 查询 该项目是否已经创建过对应流程
        List<FlowDO> designFlowList = flowService.getFlowByHouseIdAndFlowCd(id, FlowCdEnum.FLOW_CD_0.getCode());
        if (designFlowList.size() > 0) {

        }

        return null;

    }


    @GetMapping("/startProject/{houseId}")
    @Operation(summary = "启动项目")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> startProject(@PathVariable Long houseId) {

        // 校验项目数据是否存在 不存在报错
        HouseDO houseDO = houseService.validateHouseExists(houseId);
        if (StrUtil.isEmpty(houseDO.getStyle())) {

            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DESIGN_STYLE_NOT_SELECT);
        }
        boolean izPay = false;
        String outTradeNo = null;
//        if (StrUtil.isNotEmpty(houseDO.getPayOrderId())) {
//            PayOrderDO order = orderService.getOrder(Long.valueOf(houseDO.getPayOrderId()));
//            if (PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) {
//                izPay = true;
//                outTradeNo = order.getNo();
//            }
//        }
        // 判断 当前人员是否是项目关联人员（设计师）
        houseUserRelService.validateUserIsRole(houseId,
                SecurityFrameworkUtils.getLoginUserId(), DesignUserRoleEnum.DESIGN.getRoleId());
        // 校验 信息项是否完整
        /*1.检查业主是否关联*/
        houseUserRelService.validateRoleInHouse(houseId, DesignUserRoleEnum.OWNER.getRoleId());
        /*2.检查设计流程是否创建 */
        List<FlowDO> flowByHouseIdAndFlowCd = flowService.getFlowByHouseIdAndFlowCd(houseId, FlowCdEnum.FLOW_CD_0.getCode());
        /*3.检查施工流程是否创建 */
        List<FlowDO> sgFlow = flowService.getFlowByHouseIdAndFlowCd(houseId, FlowCdEnum.FLOW_CD_2.getCode());


        if (flowByHouseIdAndFlowCd.size() <= 0) {
            // TODO  增加判断 设计流程节点是否创建
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.SJ_FLOW_NOT_CREATE);
        } else {
            Long nodeCountByFlowId = nodeService.getNodeCountByFlowId(houseId, flowByHouseIdAndFlowCd.get(0).getId());

            if (nodeCountByFlowId <= 0) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.SJ_FLOW_NOT_CREATE);
            }

        }
        if (sgFlow.size() <= 0) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.SG_FLOW_NOT_CREATE);
        }
        ConfigDO config = configService.getConfigByKey(POINS_CONFIG_KEY);
        if (!StrUtil.isNotBlank(config.getValue())) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.POINTS_NOT_INFA_CONFIG);
        }
        Integer HOUSE_AMT = Integer.valueOf(config.getValue());
        if (!izPay) {
            // 检查项目是否已经支付
            /*2.检查积分是否足够  单位为分 1元 = 100分*/
//            PayWalletDO wallet = payWalletService.getOrCreateWallet(getLoginUserId(), 3);
//            Integer balance = wallet.getBalance();
//            int result = Integer.compare(balance, HOUSE_AMT);
//
//            if (result < 0) {
//                // 余额不足
//                throw exception(WALLET_BALANCE_NOT_ENOUGH);
//            } else {
//                // 创建订单
//                PayDemoOrderCreateReqVO payDemoOrderCreateReqVO = new PayDemoOrderCreateReqVO();
//                // 商品编号 6 项目服务
//                payDemoOrderCreateReqVO.setSpuId(6L);
//                // 创建支付订单
//                Long demoOrder = payDemoOrderService.createDemoOrder(getLoginUserId(), payDemoOrderCreateReqVO);
//                //  获取订单详情
//                PayOrderDO order = orderService.getOrder(9L, demoOrder.toString());
//                // 发起支付
//                // 1. 钱包支付事，需要额外传 user_id 和 user_type
//                PayOrderSubmitReqVO reqVO = new PayOrderSubmitReqVO();
//                Map<String, String> channelExtras = reqVO.getChannelExtras() == null ?
//                        Maps.newHashMapWithExpectedSize(2) : reqVO.getChannelExtras();
//                channelExtras.put(WalletPayClient.USER_ID_KEY, String.valueOf(WebFrameworkUtils.getLoginUserId()));
//                channelExtras.put(WalletPayClient.USER_TYPE_KEY, String.valueOf(3));
//                reqVO.setChannelExtras(channelExtras);
//                reqVO.setId(order.getId());
//                reqVO.setChannelCode(PayChannelEnum.WALLET.getCode());
//                //            http://localhost/pay/cashier?id=309&returnUrl=%252Fpay%252Fdemo-order%253Fid%253D183
//                reqVO.setReturnUrl("https://localhost:9001/pay/cashier?id=" + order.getId() + "&returnUrl=/pay/demo-order?id=" + order.getMerchantOrderId());
//                // 2. 提交支付
//                PayOrderSubmitRespVO respVO = orderService.submitOrder(reqVO, getClientIP());
//                if (PayOrderStatusEnum.isSuccess(respVO.getStatus())) {
//                    // submitOrder 自动调用支付 无需再次调用
////                    PayWalletTransactionDO payWalletTransactionDO = payWalletService.orderPay(getLoginUserId(), 3, respVO.getOutTradeNo(), order.getPrice());
////                    outTradeNo = respVO.getOutTradeNo();
//                    izPay = true;
//                }

                izPay = true;
//            }
        }
        // 支付状态为成功 启动项目
        if (izPay) {

            flowService.startFlowAll(houseId);
            // 发起设计流程待办
            houseService.saveFlowTask(houseDO, FlowCdEnum.FLOW_CD_0.getCode());
//            // 保存业主和设计流程关系
//            houseService.saveHouseUserFlowRel(houseDO.getId(),flowByHouseIdAndFlowCd.get(0).getId(),houseDO.getOwnerId(),DesignUserRoleEnum.OWNER.getRoleId());
            // 保存设计师和设计流程关系
            houseService.saveHouseUserFlowRel(houseDO.getId(), flowByHouseIdAndFlowCd.get(0).getId(), houseDO.getDesignerId(), DesignUserRoleEnum.DESIGN.getRoleId());

//            // 保存业主和施工流程关系
//            houseService.saveHouseUserFlowRel(houseDO.getId(),sgFlow.get(0).getId(),houseDO.getOwnerId(),DesignUserRoleEnum.OWNER.getRoleId());
            // 保存设计师和施工流程关系
            houseService.saveHouseUserFlowRel(houseDO.getId(), sgFlow.get(0).getId(), houseDO.getDesignerId(), DesignUserRoleEnum.DESIGN.getRoleId());
            // 项目关联待办
            //  给项目关联人发起待办  状态为待发起  ,如果添加好友后
            List<UserRelListVO> userRelList = houseUserRelService.getUserRelList(houseId, null);
            // jdk8 根据userId 去重 只发送一次关联项目请求
            List<UserRelListVO> distinctHouses = userRelList.stream()
                    .collect(Collectors.collectingAndThen(
                            Collectors.toCollection(() -> new ArrayList<>(userRelList)),
                            housesList -> housesList.stream()
                                    .collect(Collectors.toMap(UserRelListVO::getUserId, userRel -> userRel, (a, b) -> a))
                                    .values().stream()
                                    .collect(Collectors.toList())
                    ));
            // 查询当前登陆人好友关系
            Long loginUserId = getLoginUserId();
            List<RelativedDO> relativedList = relativedService.getRelativedList(loginUserId,
                    UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode().toString());
            Set<String> relUserIdsSet = relativedList.stream()
                    .map(RelativedDO::getRelUserId)
                    .collect(Collectors.toSet());
            for (UserRelListVO userRelVO : distinctHouses) {
                // 检查userId 和 当前登陆人是否是好友关系  状态正常则status为1  待处理为 0
                Integer statusCd = relUserIdsSet.contains(userRelVO.getUserId().toString()) ?
                        UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode() : userRelVO.getStatus();

                flowTaskService.createHouseUserRelFlowTask(houseId, houseDO.getProjectName(),
                        userRelVO.getUserId(), userRelVO.getRoleId(), statusCd);
            }
            // 项目改为进行中
            houseService.startHouseStatus(houseId, outTradeNo);
        }
        return success(1L);
    }

    @GetMapping("/getSimFriendListSelect")
    @Operation(summary = "查询好友关联人")
    @PreAuthorize("@ss.hasPermission('hd:relatived:query')")
    public CommonResult<List<Map<String, Object>>> getSimFriendListSelect() {
        List<Map<String, Object>> dataList = relativedService.getSimFriendList();

        List<Map<String, Object>> resultList = dataList.stream()
                .filter(map -> filterByRoleIds(FILTER_ROLE_IDS, map))
                .collect(Collectors.groupingBy(map -> map.get("roleId")))
                .entrySet()
                .stream()
                .map(entry -> {
                    Map<String, Object> result = new HashMap<>();
                    result.put("value", entry.getKey());
                    result.put("label", entry.getValue().get(0).get("roleName"));
                    List<Map<String, Object>> children = entry.getValue()
                            .stream()
                            .map(childMap -> {
                                Map<String, Object> child = new HashMap<>();
                                child.put("value", childMap.get("relUserId"));
                                child.put("label", childMap.get("nickName"));
                                child.put("extra", childMap);
                                return child;
                            })
                            .collect(Collectors.toList());
                    result.put("children", children);
                    return result;
                })
                .collect(Collectors.toList());


        return success(resultList);
    }

    private static boolean filterByRoleIds(List<Long> filterRoleIds, Map<String, Object> map) {
        return filterRoleIds.contains(map.get("roleId"));
    }


    @PostMapping("/updateHouseStartTwo")
    @Operation(summary = "补充相关人员")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> updateHouseStartTwo(@Valid @RequestBody HouseTwoReqVO createReqVO) {

        log.debug("========  补充相关人员  Async start ==============");
        HouseDO houseDO = houseService.validateHouseExists(createReqVO.getId());
        Long houseId = houseDO.getId();

        List<HouseTwoUserReqVO> userList = createReqVO.getUserList();
        // 页面输入关联人    过滤 mobile 和 nickName 都为空的数据(不考虑把存量客户改为空的情况)
        List<HouseTwoUserReqVO> inputUserList = userList.stream()
                .filter(user -> StrUtil.isNotEmpty(user.getMobile()) && StrUtil.isNotEmpty(user.getNickName()))
                .collect(Collectors.toList());


        for (HouseTwoUserReqVO userReq : inputUserList) {
            //查询用户是否新建  没有新建则新建 新建则返回
            Long userId = houseService.createUserRel(userReq.getNickName(), userReq.getMobile()
                    , userReq.getRoleId().toString());
            userReq.setId(userId);
        }

        // 存量关联人
        List<UserRelListVO> exitUserList = houseUserRelService.getUserRelList(houseId, null);

        // 筛选出输入的新的关联人不在存量关联人中的用户   需要找出 id 相同角色不同的人
        List<HouseTwoUserReqVO> addUserList = inputUserList.stream()
                .filter(user -> !exitUserList.contains(user)) // 过滤出不在exitUserList中的用户
                .filter(user -> exitUserList.stream().noneMatch(exitUser -> exitUser.getUserId().equals(user.getId()) && exitUser.getRoleId().equals(user.getRoleId()))) // 过滤出userId相同但roleId不同的用户
                .collect(Collectors.toList());

        if (CollUtil.isNotEmpty(addUserList)) {
            // 查询当前登陆人好友关系
            Long loginUserId = getLoginUserId();
            List<RelativedDO> relativedList = relativedService.getRelativedList(loginUserId,
                    UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode().toString());
            Set<String> relUserIdsSet = relativedList.stream()
                    .map(RelativedDO::getRelUserId)
                    .collect(Collectors.toSet());


            // 发送好友 发送待办
            Set<Long> userIds = new HashSet<>();
            for (HouseTwoUserReqVO houseTwoUserReqVO : addUserList) {
                // 判断用户是否在项目中  在项目中就删除对应角色   添加新用户  状态为通过
                // 不在项目中  删除对应角色 添加新用户 状态为 待处理
                houseUserRelService.saveHouseUserRel(createReqVO.getId(), houseTwoUserReqVO.getId(), houseTwoUserReqVO.getRoleId());
                if (!userIds.contains(houseTwoUserReqVO.getId())) {
                    // 检查userId 和 当前登陆人是否是好友关系  状态正常则status为1  待处理为 0
                    Integer statusCd = relUserIdsSet.contains(houseTwoUserReqVO.getId().toString()) ?
                            UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode() : UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode();
                    flowTaskService.createHouseUserRelFlowTask(houseId, houseDO.getProjectName(),
                            houseTwoUserReqVO.getId(), houseTwoUserReqVO.getRoleId(), statusCd);
                    userIds.add(houseTwoUserReqVO.getId());
                }

            }
            // 筛选出项目经理 存量项目经理是否有值 有值则修改flowTask 和node节点处理人
            List<UserRelListVO> exitProjectManagerList = exitUserList.stream()
                    .filter(user -> user.getRoleId().toString().equals(DesignUserRoleEnum.PROJECT_MANAGER.getRoleId().toString())) // 过滤出roleId为114的用户
                    .collect(Collectors.toList());

            List<HouseTwoUserReqVO> projectManagerList = addUserList.stream()
                    .filter(user -> user.getRoleId().toString().equals(DesignUserRoleEnum.PROJECT_MANAGER.getRoleId().toString())) // 过滤出roleId为114的用户
                    .collect(Collectors.toList());
            if (CollUtil.isNotEmpty(exitProjectManagerList) && CollUtil.isNotEmpty(projectManagerList)) {
                for (HouseTwoUserReqVO projectManager : projectManagerList) {
                    if (!projectManager.getId().toString().equals(exitProjectManagerList.get(0).getUserId())) {
                        // 修改对应任务处理人
                        flowTaskService.updateFlowTaskDealerId(houseId, exitProjectManagerList.get(0).getUserId(),
                                projectManager.getId());
                        // 修改对应node 处理人
                        nodeService.updateNodeDealerId(houseId, exitProjectManagerList.get(0).getUserId(),
                                projectManager.getId());
                    }
                }
            }


        }
        // 筛选出存量关联人 不在输入的关联人中的用户( 不包括 业主和设计师) 进行删除  之后发通知
        List<UserRelListVO> deleteUserList = exitUserList.stream()
                .filter(userB -> !inputUserList.stream().anyMatch(userA -> userA.getId().equals(userB.getUserId())))
                .collect(Collectors.toList());

        Set<Long> deleteUserIds = deleteUserList.stream()
                .filter(userB -> !userB.getRoleId().toString().equals(DesignUserRoleEnum.DESIGN.getRoleId().toString())
                        && !userB.getRoleId().toString().equals(DesignUserRoleEnum.OWNER.getRoleId().toString()))
                .map(UserRelListVO::getUserId)
                .collect(Collectors.toSet());
        // saveHouseUserRel 会删除对应角色  这里无需操作
        //  只负责 删除 未处理的待办 flowTask
        if (CollUtil.isNotEmpty(deleteUserIds)) {
            flowTaskService.deleteFlowTaskByHouseIdAndUserId(houseId, deleteUserIds, FlowTaskTypeEnum.FLOW_TASk_CD_2.getCode());

        }

        // 项目关联待办
        //  给项目关联人发起待办  状态为待发起  ,如果添加好友后
//        List<UserRelListVO> userRelList = houseUserRelService.getUserRelList(houseId, null);
//        // jdk8 根据userId 去重 只发送一次关联项目请求
//        List<UserRelListVO> distinctHouses = userRelList.stream()
//                .collect(Collectors.collectingAndThen(
//                        Collectors.toCollection(() -> new ArrayList<>(userRelList)),
//                        housesList -> housesList.stream()
//                                .collect(Collectors.toMap(UserRelListVO::getUserId, userRel -> userRel, (a, b) -> a))
//                                .values().stream()
//                                .collect(Collectors.toList())
//                ));
//        for (UserRelListVO userRelVO:distinctHouses ) {
//            flowTaskService.createUserRelFlowTask(houseId, houseDO.getProjectName(),
//                    userRelVO.getUserId(),userRelVO.getRoleId(),userRelVO.getStatus());
//        }
        // 同意项目关联后 开始关联userRelFlow

        log.debug("========  补充相关人员  Async end ==============");

        return success(1L);
    }

    @PostMapping("/updateHouseStartOne")
    @Operation(summary = "修改创建项目步骤1")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> updateHouseStartOne(@Valid @RequestBody HouseOneReqVO createReqVO) {

        // 启动项目后修改基本信息
        houseService.updateBusinessHouse(createReqVO);

        return success(createReqVO.getId());
    }


    @PostMapping("/addHouseRelFamilyUser")
    @Operation(summary = "添加亲友一起盯")
    @PreAuthorize("@ss.hasPermission('design:house:create')")
    public CommonResult<Long> addHouseRelFamilyUser(@Valid @RequestBody HouseOneReqVO createReqVO) {

        // 启动项目后修改基本信息
        houseService.updateBusinessHouse(createReqVO);

        return success(createReqVO.getId());
    }

}
